/**
 ******************************************************************************
 * @file    zb32l03x_hal_lptim.c
 * @author  MCU Software Team
 * @Version V1.1.0
 * @Date    2022/01/19
 * @brief   LPTIM HAL module driver
 *          This file provides firmware functions to manage the following
 *          functionalities of the Low Power Timer (LPTIM) peripheral:
 *           + Low Power Time Base Initialization
 *           + Low Power Time Base Start
 *           + Low Power Time Base Start Interruption
 @verbatim
 ==============================================================================
                 ##### LOW POWER TIMER Generic features #####
 ==============================================================================
 [..] The Timer features include:
      (#) 16-bit up auto-reload counter.
 @endverbatim
 ******************************************************************************
 **/


#include "zb32l03x_hal.h"


/** @addtogroup ZB32L03x_HAL_Driver
 * @{
 */

/** @defgroup LPTIM LPTIM
 * @brief LPTIM HAL module driver
 * @{
 */
#if defined(HAL_LPTIM_MODULE_ENABLED)


/** @defgroup LPTIM_Private_Functions LPTIM Private Functions
 * @{
 */

/**
 * @brief  Low Power Time Base configuration
 * @param  LPTIMx : LPTIM periheral
 * @param  Structure : LPTIM Base configuration structure
 * @retval None
 */
static void LPTIM_Base_SetConfig(LPTIM_TypeDef *LPTIMx, LPTIM_Base_InitTypeDef *Structure)
{
    /* Reset all low power timer function */
    LPTIMx->CR = Structure->GateLevel | Structure->GateEnable | Structure->TogEnable | \
                 Structure->CntTimSel | Structure->AutoReload | Structure->ClkSel;
    LPTIMx->CR |= LPTIM_CR_TCK_EN;
}

/**
 * @brief  WT Indicates the write synchronization flag
 * @param  LPTIMx : LPTIM periheral
 * @param  Timeout : Timeout period
 * @param  Structure : LPTIM Base configuration structure
 * @retval None
 */
static HAL_StatusTypeDef LPTIM_Wait_WTFlag(LPTIM_TypeDef *LPTIMx,uint32_t Timeout)
{
    uint32_t tickstart = 0;
    tickstart = HAL_GetTick();

    while(__HAL_LPTIM_SYNC_FLAG(LPTIMx) == SET)
    {
        if((HAL_GetTick() - tickstart) > Timeout)
        {
            return HAL_TIMEOUT;
        }
    }
    return HAL_OK;
}

void LPTIM_Update_Period(LPTIM_HandleTypeDef *hlptim,uint16_t Value)
{
    if(LPTIM_Wait_WTFlag(hlptim->Instance,200) == HAL_TIMEOUT) return;

    __disable_irq();
    hlptim->Instance->LOAD = Value;

    if(LPTIM_Wait_WTFlag(hlptim->Instance,200) == HAL_TIMEOUT) return;
    hlptim->Instance->LOAD = Value;
    
    __enable_irq();
    
    /* mode  2  support */
    if(hlptim->Init.AutoReload == LPTIM_AUTORELOAD_ENABLE)
    {
        if(LPTIM_Wait_WTFlag(hlptim->Instance,200) == HAL_TIMEOUT) return;
        hlptim->Instance->BGLOAD = Value;
    }
}
/** @defgroup LPTIM_Exported_Functions LPTIM Exported Functions
 * @{
 */

/** @defgroup LPTIM_Exported_Functions_Group Low Power Time Base functions
 *  @brief    Low Power Time Base functions
 *
 @verbatim
  ==============================================================================
              ##### Low Power Time Base functions #####
  ==============================================================================
  [..]
    This section provides functions allowing to:
    (+) Initialize and configure the Low Power Time.
    (+) De-initialize the Low Power Time.
    (+) Start the Low Power Time.
    (+) Stop the Low Power Time.
    (+) Start the Low Power Time and enable interrupt.
    (+) Stop the Low Power Time and disable interrupt.

 @endverbatim
 * @{
 */

/**
 * @brief  Initializes the LPTIM Time base Unit according to the specified
 *         parameters in the LPTIM_HandleTypeDef and create the associated handle.
 * @note no comment
 * @param  hlptim : LPTIM Base handle
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_LPTIM_Base_Init(LPTIM_HandleTypeDef *hlptim)
{
    /* Check the LPTIM handle allocation */
    if(hlptim == NULL)
        return HAL_ERROR;

    /* Check the parameters */
    assert_param(hlptim);
    assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));

    if(hlptim->State == HAL_LPTIM_STATE_RESET)
    {
        /* Allocate lock resource and initialize it */
        hlptim->Lock = HAL_UNLOCKED;

        __HAL_LPTIM_CLOCK_ENABLE(hlptim);

        /* Init the low level hardware : GPIO, CLOCK, NVIC */
        HAL_LPTIM_Base_MspInit(hlptim);
    }

    /* Set the LPTIM state */
    hlptim->State = HAL_LPTIM_STATE_BUSY;

    /* Set the Low Power Time Base configuration */
    LPTIM_Base_SetConfig(hlptim->Instance, &hlptim->Init);
    LPTIM_Update_Period(hlptim,hlptim->Init.Period);
    /* Initialize the LPTIM state*/
    hlptim->State = HAL_LPTIM_STATE_READY;

    return HAL_OK;
}


/**
 * @brief  DeInitializes the LPTIM Base peripheral
 * @param  hlptim : LPTIM Base handle
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_LPTIM_Base_DeInit(LPTIM_HandleTypeDef *hlptim)
{
    /* Check the parameters */
    assert_param(hlptim);
    assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));

    hlptim->State = HAL_LPTIM_STATE_BUSY;

    /* Disable the LPTIM Clock */
    __HAL_LPTIM_CLOCK_DISABLE(hlptim);

    /* Stop LPTIM */
    __HAL_LPTIM_DISABLE(hlptim);

    /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
    HAL_LPTIM_Base_MspDeInit(hlptim);

    /* Change LPTIM state */
    hlptim->State = HAL_LPTIM_STATE_RESET;

    /* Release Lock */
    __HAL_UNLOCK(hlptim);

    return HAL_OK;
}


/**
 * @brief  Starts the LPTIM Base generation.
 * @param  hlptim : LPTIM handle
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_LPTIM_Base_Start(LPTIM_HandleTypeDef *hlptim)
{
    /* Check the parameters */
    assert_param(hlptim);
    assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));

    /* Set the LPTIM state */
    hlptim->State = HAL_LPTIM_STATE_BUSY;

    /* Start the lptim*/
    __HAL_LPTIM_ENABLE(hlptim);

    /* Change the LPTIM state*/
    hlptim->State = HAL_LPTIM_STATE_READY;

    /* Return function status */
    return HAL_OK;
}


/**
 * @brief  Stops the LPTIM Base generation.
 * @param  hlptim : LPTIM handle
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_LPTIM_Base_Stop(LPTIM_HandleTypeDef *hlptim)
{
    /* Check the parameters */
    assert_param(hlptim);
    assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));

    /* Set the LPTIM state */
    hlptim->State = HAL_LPTIM_STATE_BUSY;

    /* Stop lptim */
    __HAL_LPTIM_DISABLE(hlptim);

    /* Change the LPTIM state*/
    hlptim->State = HAL_LPTIM_STATE_READY;

    /* Return function status */
    return HAL_OK;
}


/**
 * @brief  Starts the LPTIM Base generation in interrupt mode.
 * @param  hlptim : LPTIM handle
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_LPTIM_Base_Start_IT(LPTIM_HandleTypeDef *hlptim)
{
    /* Check the parameters */
    assert_param(hlptim);
    assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));

    /* Enable the LPTIM interrupt */
    __HAL_LPTIM_ENABLE_IT(hlptim);

    /* start the Peripheral */
    __HAL_LPTIM_ENABLE(hlptim);

    /* Return function status */
    return HAL_OK;
}


/**
 * @brief  Stops the LPTIM Base generation in interrupt mode.
 * @param  hlptim : LPTIM handle
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_LPTIM_Base_Stop_IT(LPTIM_HandleTypeDef *hlptim)
{
    /* Check the parameters */
    assert_param(hlptim);
    assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));

    /* Disable the LPTIM interrupt */
    __HAL_LPTIM_DISABLE_IT(hlptim);

    /* Stop lptim */
    __HAL_LPTIM_DISABLE(hlptim);

    /* Return function status */
    return HAL_OK;
}


/**
 * @brief  Initializes the LPTIM Base MSP.
 * @param  hlptim : LPTIM handle
 * @retval None
 */
__weak void HAL_LPTIM_Base_MspInit(LPTIM_HandleTypeDef *hlptim)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(hlptim);
    /* NOTE : This function Should not be modified, when the callback is needed,
              the HAL_LPTIM_Base_MspInit could be implemented in the user file
     */
}


/**
 * @brief  DeInitializes LPTIM Base MSP.
 * @param  hlptim : LPTIM handle
 * @retval None
 */
__weak void HAL_LPTIM_Base_MspDeInit(LPTIM_HandleTypeDef *hlptim)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(hlptim);
    /* NOTE : This function Should not be modified, when the callback is needed,
              the HAL_LPTIM_Base_MspDeInit could be implemented in the user file
     */
}


/**
 * @brief  This function handles LPTIM interrupts requests.
 * @param  htim : LPTIM handle
 * @retval None
 */
void HAL_LPTIM_IRQHandler(LPTIM_HandleTypeDef *hlptim)
{
    /* TIM Update event */
    if(__HAL_LPTIM_GET_FLAG(hlptim) != RESET)
    {
        if(__HAL_LPTIM_GET_IT_SOURCE(hlptim) != RESET)
        {
            __HAL_BASETIM_CLEAR_IT(hlptim);
            HAL_LPTIM_PeriodElapsedCallback(hlptim);
        }
    }
}

/**
 * @brief  Period elapsed callback in non blocking mode
 * @param  htim : LPTIM handle
 * @retval None
 */
__weak void HAL_LPTIM_PeriodElapsedCallback(LPTIM_HandleTypeDef *hlptim)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(hlptim);
    /* NOTE : This function Should not be modified, when the callback is needed,
              the HAL_LPTIM_PeriodElapsedCallback could be implemented in the user file
     */

}



/**
 * @}
 */ /* End of group LPTIM_Exported_Functions_Group */


/**
 * @}
 */ /* End of group LPTIM_Exported_Functions */



#endif /* HAL_LPTIM_MODULE_ENABLED */
/**
 * @}
 */ /* End of group LPTIM */



/**
 * @}
 */ /* group ZB32L03x_HAL_Driver */
